﻿using System;
using System.Linq;
using System.Activities;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.TestManagement.Client;
using StatlightTfsBuildIntegration.Statlight;
using StatlightTfsBuildIntegration.TestResultService;
using System.Activities;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Workflow.Activities;
using System.ServiceModel;
using Microsoft.TeamFoundation.Client;
using StatlightTfsBuildIntegration.IdentityManagementService;
using System.Security.Principal;
using StatlightTfsBuildIntegration.TfsServiceUtil;

// for inspiration see http://nunit4teambuild.codeplex.com/SourceControl/changeset/view/44210#980040
// http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx
// http://statlight.codeplex.com/discussions/226475

namespace StatlightTfsBuildIntegration.Activities
{
	[BuildActivity(HostEnvironmentOption.All)]
	public sealed class StatlightIntegration : CodeActivity
	{
		// Define an activity input argument of type string
		public InArgument<string> FilenameExport { get; set; }

		public InArgument<IBuildDetail> BuildDetail { get; set; }

		// If your activity returns a value, derive from CodeActivity<TResult>
		// and return the value from the Execute method.
		protected override void Execute(CodeActivityContext context)
		{
			context.TrackBuildMessage("Start publishing results");

			// Init input parameters
			string filenameStatlightResult = context.GetValue(this.FilenameExport);
			IBuildDetail buildDetail = context.GetValue(this.BuildDetail);

			string url = buildDetail.BuildServer.TeamProjectCollection.ConfigurationServer.Uri.ToString();
			context.TrackBuildMessage("tfs server url: " + url);
			ServiceClientFactory.TfsUrl = url;

			Guid userId = IdentityManagement.ReadCurrentUsersIdentity();

			string platform = "Any CPU";
			string flavor = "Release";
		
			context.TrackBuildMessage("Initial values are set");

			// Read and parse testresults
			try
			{
				var testResult = TestBuilder.Parse(filenameStatlightResult);
				context.TrackBuildMessage("results parsed #" + testResult.TestList.Count);

				using (var serviceClient = ServiceClientFactory.CreateTestResultsServiceSoapClients())
				{
					var testRun = new StatlightTfsBuildIntegration.TestResultService.TestRun
					{
						Title = testResult.Name,
						Owner = userId,
						State = (byte)TestRunState.InProgress,
						BuildUri = buildDetail.Uri.ToString(),
						BuildNumber = buildDetail.BuildNumber,
						BuildPlatform = platform,
						BuildFlavor = flavor,
						// TODO: Get correct times into <Times> element and use those instead.
						StartDate = testResult.StartTime,
						CompleteDate = testResult.StartTime.AddMinutes(1),
						PostProcessState = (byte)PostProcessState.Complete,
						Iteration = buildDetail.TeamProject,
						Version = 1000,
						TeamProject = buildDetail.TeamProject,
					};
					testRun = serviceClient.CreateTestRun(testRun, buildDetail.TeamProject);
					context.TrackBuildMessage("testrun aangemaakt: " + testRun.TestRunId);

					List<Tuple<StatlightTfsBuildIntegration.Statlight.Test, TestCaseResult>> testCaseResults = new List<Tuple<StatlightTfsBuildIntegration.Statlight.Test, TestCaseResult>>();
					int testResultId = 0;
					foreach (var test in testResult.TestList)
					{
						TestCaseResult testCaseResult = new TestCaseResult
						{
							ResolutionStateId = -1,
							Owner = userId,
							RunBy = userId,
							TestCaseTitle = test.Name,
							AutomatedTestName = test.Name,
							AutomatedTestType = "Unit Test",
							AutomatedTestId = Guid.NewGuid().ToString("D"),
							Id = new StatlightTfsBuildIntegration.TestResultService.TestCaseResultIdentifier
								 {
									 TestRunId = testRun.TestRunId,
									 TestResultId = testResultId++
								 },

						};
						context.TrackBuildMessage("test result: " + test);


						testCaseResults.Add(new Tuple<StatlightTfsBuildIntegration.Statlight.Test, TestCaseResult>(test, testCaseResult));
					}
					serviceClient.CreateTestResults(testCaseResults.Select(x => x.Item2).ToArray(), buildDetail.TeamProject);

					List<ResultUpdateRequest> updateRequests = new List<ResultUpdateRequest>();
					foreach (var t in testCaseResults)
					{
						var test = t.Item1;
						var testCaseResult = t.Item2;

						var updateRequest = new ResultUpdateRequest();
						updateRequest.TestRunId = testCaseResult.Id.TestRunId;
						updateRequest.TestResultId = testCaseResult.Id.TestResultId;
						updateRequest.TestCaseResult = testCaseResult;
						updateRequests.Add(updateRequest);

						switch (test.Result)
						{
							case Statlight.TestResult.Pass:
								testCaseResult.Outcome = (byte)TestOutcome.Passed;

								break;
							case Statlight.TestResult.Fail:
								testCaseResult.Outcome = (byte)TestOutcome.Failed;
								testCaseResult.ErrorMessage = test.Message;
								break;
							case Statlight.TestResult.Inconclusive:
								testCaseResult.Outcome = (byte)TestOutcome.Inconclusive;
								break;
							case Statlight.TestResult.Unknown:
								testCaseResult.Outcome = (byte)TestOutcome.Unspecified;
								break;
						}
					}

					serviceClient.UpdateTestResults(updateRequests.ToArray(), buildDetail.TeamProject);
					context.TrackBuildMessage("testlist saved!");
				}
			}
			catch (Exception e)
			{
				context.TrackBuildMessage("error : " + e.Message);
				buildDetail.Information.AddBuildError("Error while parsing statlight results: " + e.Message, DateTime.Now);
				throw;
			}
		}



		public Guid IdentityManangement { get; set; }
	}
}
